package org.rslai.tcedit.security.SecureFilter;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.framework.ReflectiveMethodInvocation;
import org.springframework.security.intercept.method.MethodDefinitionSource;
import org.springframework.security.ConfigAttribute;
import org.springframework.security.ConfigAttributeDefinition;
import org.springframework.security.SecurityConfig;
import org.springframework.web.context.ServletContextAware;

/**
 * @author rslai
 */
public class MethodInvocationDefinitionSource implements MethodDefinitionSource, ServletContextAware {
	protected Log log = LogFactory.getLog(getClass());

	private ServletContext servletContext;

	public ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException {
		ReflectiveMethodInvocation rmi = (ReflectiveMethodInvocation) object;
		String methodName = rmi.getThis().getClass().getName() + "." + rmi.getMethod().getName();

		Map<String, List<String>> methodAuthorities = getMethodAuthorities();
		if (methodAuthorities == null) {
			return null;
		}

		List<String> roleList = methodAuthorities.get(methodName);
		if (roleList == null) {
			return null;
		} else {
			List<ConfigAttribute> attributes = new LinkedList<ConfigAttribute>();
			for (String roleName : roleList) {
				attributes.add(new SecurityConfig(roleName));
			}

			if (log.isDebugEnabled()) {
				StringBuffer logStr = new StringBuffer();
				logStr.append("请求Method允许访问角色：");
				logStr.append(methodName);
				logStr.append("=");
				logStr.append(attributes);
				log.debug(logStr.toString());
			}

			return new ConfigAttributeDefinition(attributes);
		}
	}

	public ConfigAttributeDefinition getAttributes(Method method, Class clazz) {
		return null;
	}

	public Collection getConfigAttributeDefinitions() {
		return null;
	}

	public boolean supports(Class clazz) {
		return MethodInvocation.class.isAssignableFrom(clazz);
	}

	/**
	 * 实现 ServletContextAware 接口需要的方法，初始化 ServletContext
	 */
	public void setServletContext(ServletContext servletContext) {
		this.servletContext = servletContext;
	}

	/**
	 * 从 ServletContext 取回 methodAuthorities
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private Map<String, List<String>> getMethodAuthorities() {
		return (Map<String, List<String>>) servletContext.getAttribute("methodAuthorities");
	}

}